﻿using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Drawing.Text;
using System.Globalization;
using System.IO;
using System.Security.Cryptography;
using System.Text;

// ReSharper disable once CheckNamespace

namespace Web.Security
{

    #region 验证码生成类

    /// <summary>
    ///     验证码生成类
    /// </summary>
    public class Captcha
    {
        /// <summary>
        ///     构造函数,用于初始化常用变量
        /// </summary>
        public Captcha()
        {
            _randomNumber = new Random(Guid.NewGuid().GetHashCode());
            _stringPoint = new Point[_length + 1];
            if (GaussianDeviation < 0) GaussianDeviation = 0;
        }

        /// <summary>
        ///     生成验证码
        /// </summary>
        /// <param name="target">用于存储图片的一般字节序列</param>
        public void CreateImage(Stream target)
        {
            var randomNumber = new Random();
            var bit = new Bitmap(_width + 1, _height + 1);
            //写字符串
            _image = Graphics.FromImage(bit);
            _image.SmoothingMode = SmoothingMode.HighQuality;
            _image.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
            _image.InterpolationMode = InterpolationMode.HighQualityBilinear;
            _image.CompositingQuality = CompositingQuality.HighQuality;

            _image.Clear(Color.White);
            _image.DrawImageUnscaled(DrawBackground(), 0, 0);
            _image.DrawImageUnscaled(DrawRandomString(), 0, 0);
            //对图片文字进行扭曲
            bit = AdjustRippleEffect(bit, Convert.ToSByte(randomNumber.Next()%5));
            //对图片进行高斯模糊
            if (GaussianDeviation > 0)
            {
                var gau = new Gaussian();
                bit = gau.FilterProcessImage(GaussianDeviation, bit);
            }
            //进行暗度和亮度处理
            if (IsChangeBrightness != 0)
            {
                //对图片进行调暗处理
                bit = AdjustBrightness(bit, IsChangeBrightness);
            }
            bit.Save(target, ImageFormat.Gif);
            bit.Dispose();
            _image.Dispose();
        }

        #region 画验证码背景,例如,增加噪点,添加曲线和直线等

        /// <summary>
        ///     画验证码背景,例如,增加噪点,添加曲线和直线等
        /// </summary>
        /// <returns></returns>
        private Bitmap DrawBackground()
        {
            var bit = new Bitmap(_width + 1, _height + 1);
            var g = Graphics.FromImage(bit);
            g.SmoothingMode = SmoothingMode.HighQuality;

            g.Clear(Color.White);
            var rectangle = new Rectangle(0, 0, _width, _height);
            Brush brush = new SolidBrush(_backColor);
            g.FillRectangle(brush, rectangle);

            //画噪点
            if (_isPixel)
            {
                g.DrawImageUnscaled(DrawRandomPixel(30), 0, 0);
            }
            g.DrawImageUnscaled(DrawRandBgString(), 0, 0);


            //画曲线
            g.DrawImageUnscaled(DrawRandomBezier(_bezierCount), 0, 0);
            //画直线
            g.DrawImageUnscaled(DrawRandomLine(_lineCount), 0, 0);

            //dc.DrawImageUnscaled(DrawStringline(), 0, 0);
            switch (Border)
            {
                case BorderStyle.Rectangle:
                    g.DrawRectangle(new Pen(Color.FromArgb(90, 87, 46)), 0, 0, _width, _height);
                    break;
                case BorderStyle.RoundRectangle:
                    DrawRoundRectangle(g, rectangle, Color.FromArgb(90, 87, 46), 1, 3);
                    break;
            }

            return bit;
        }

        #endregion

        #region 画正弦曲线

        private Bitmap DrawTwist(Bitmap bmp, Int32 tWidth, Int32 tHeight, float angle, Color color)
        {
            //为了方便查看效果,在这里我定义了一个常量
            //它在定义数组的长度和for循环中都要用到
            var size = _width;

            var x = new double[size];
            var b = new Bitmap(bmp.Width, bmp.Height);
            b.MakeTransparent();
            var graphics = Graphics.FromImage(b);
            var pen = new Pen(color);

            //画正弦曲线的横轴间距参数建议所用的值应该是 正数且是2的倍数
            //在这里采用2
            const Int32 val = 2;

            var temp = 0.0f;

            graphics.TranslateTransform(0, 100);
            graphics.SmoothingMode = SmoothingMode.HighQuality;
            graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
            for (var i = 0; i < size; i++)
            {
                //改变tWidth,实现正弦曲线宽度的变化
                //改tHeight,实现正弦曲线高度的变化
                x[i] = Math.Sin(2*Math.PI*i/tWidth)*tHeight;

                graphics.DrawLine(pen, i*val, temp, i*val + val/2, (float) x[i]);
                temp = (float) x[i];
            }
            graphics.RotateTransform(60, MatrixOrder.Prepend);

            //旋转图片
            b = KiRotate(b, angle, Color.Transparent);
            return b;
        }

        #endregion

        #region 正弦曲线Wave扭曲图片

        /// <summary>
        ///     正弦曲线Wave扭曲图片
        /// </summary>
        /// <param name="srcBmp">图片路径</param>
        /// <param name="bXDir">如果扭曲则选择为True</param>
        /// <param name="dMultValue">波形的幅度倍数,越大扭曲的程度越高,一般为3</param>
        /// <param name="dPhase">波形的起始相位,取值区间[0-2*PI)</param>
        /// <returns></returns>
        public Bitmap TwistImage(Bitmap srcBmp, bool bXDir, double dMultValue, double dPhase)
        {
            var destBmp = new Bitmap(srcBmp.Width, srcBmp.Height);
            const double pi2 = Math.PI*2;
            // 将位图背景填充为白色
            var graph = Graphics.FromImage(destBmp);
            graph.FillRectangle(new SolidBrush(Color.White), 0, 0, destBmp.Width, destBmp.Height);
            graph.Dispose();

            double dBaseAxisLen = bXDir ? destBmp.Height : destBmp.Width;

            for (var i = 0; i < destBmp.Width; i++)
            {
                for (var j = 0; j < destBmp.Height; j++)
                {
                    var dx = bXDir ? (pi2*j)/dBaseAxisLen : (pi2*i)/dBaseAxisLen;
                    dx += dPhase;
                    var dy = Math.Sin(dx);

                    // 取得当前点的颜色
                    var nOldX = bXDir ? i + (int) (dy*dMultValue) : i;
                    var nOldY = bXDir ? j : j + (int) (dy*dMultValue);

                    var color = srcBmp.GetPixel(i, j);
                    if (nOldX >= 0 && nOldX < destBmp.Width
                        && nOldY >= 0 && nOldY < destBmp.Height)
                    {
                        destBmp.SetPixel(nOldX, nOldY, color);
                    }
                }
            }
            return destBmp;
        }

        #endregion

        #region 图片任意角度旋转

        /// <summary>
        ///     图片任意角度旋转
        /// </summary>
        /// <param name="bmp">原始图Bitmap</param>
        /// <param name="angle">旋转角度</param>
        /// <param name="bkColor">背景色</param>
        /// <returns>输出Bitmap</returns>
        public static Bitmap KiRotate(Bitmap bmp, float angle, Color bkColor)
        {
            var w = bmp.Width;
            var h = bmp.Height;

            var pf = bkColor == Color.Transparent ? PixelFormat.Format32bppArgb : bmp.PixelFormat;

            var tmp = new Bitmap(w, h, pf);
            var g = Graphics.FromImage(tmp);
            g.Clear(bkColor);
            g.DrawImageUnscaled(bmp, 1, 1);
            g.Dispose();

            var path = new GraphicsPath();
            path.AddRectangle(new RectangleF(0f, 0f, w, h));
            var mtrx = new Matrix();
            mtrx.Rotate(angle);
            var rct = path.GetBounds(mtrx);

            var dst = new Bitmap((int) rct.Width, (int) rct.Height, pf);
            g = Graphics.FromImage(dst);
            g.Clear(bkColor);
            g.TranslateTransform(-rct.X, -rct.Y);
            g.RotateTransform(angle);
            g.InterpolationMode = InterpolationMode.HighQualityBilinear;
            g.DrawImageUnscaled(tmp, 0, 0);
            g.Dispose();
            tmp.Dispose();

            return dst;
        }

        #endregion

        #region 随机生成贝塞尔曲线

        /// <summary>
        ///     随机生成贝塞尔曲线
        /// </summary>
        /// <param name="lineNum">线条数量</param>
        /// <returns></returns>
        public Bitmap DrawRandomBezier(Int32 lineNum)
        {
            var b = new Bitmap(_width, _height);
            b.MakeTransparent();
            var g = Graphics.FromImage(b);
            g.Clear(Color.Transparent);
            g.SmoothingMode = SmoothingMode.HighQuality;
            g.PixelOffsetMode = PixelOffsetMode.HighQuality;

            var gPath1 = new GraphicsPath();
            var lineRandNum = _randomNumber.Next(lineNum);

            for (var i = 0; i < (lineNum - lineRandNum); i++)
            {
                var p = new Pen(GetRandomDeepColor());
                Point[] point =
                {
                    new Point(_randomNumber.Next(1, (b.Width/10)), _randomNumber.Next(1, (b.Height))),
                    new Point(_randomNumber.Next((b.Width/10)*2, (b.Width/10)*4), _randomNumber.Next(1, (b.Height))),
                    new Point(_randomNumber.Next((b.Width/10)*4, (b.Width/10)*6), _randomNumber.Next(1, (b.Height))),
                    new Point(_randomNumber.Next((b.Width/10)*8, b.Width), _randomNumber.Next(1, (b.Height)))
                };

                gPath1.AddBeziers(point);
                g.DrawPath(p, gPath1);
                p.Dispose();
            }
            for (var i = 0; i < lineRandNum; i++)
            {
                var p = new Pen(GetRandomDeepColor());
                Point[] point =
                {
                    new Point(_randomNumber.Next(1, b.Width), _randomNumber.Next(1, b.Height)),
                    new Point(_randomNumber.Next((b.Width/10)*2, b.Width), _randomNumber.Next(1, b.Height)),
                    new Point(_randomNumber.Next((b.Width/10)*4, b.Width), _randomNumber.Next(1, b.Height)),
                    new Point(_randomNumber.Next(1, b.Width), _randomNumber.Next(1, b.Height))
                };
                gPath1.AddBeziers(point);
                g.DrawPath(p, gPath1);
                p.Dispose();
            }
            return b;
        }

        #endregion

        #region 画直线

        /// <summary>
        ///     画直线
        /// </summary>
        /// <param name="lineNum">线条个数</param>
        /// <returns></returns>
        public Bitmap DrawRandomLine(Int32 lineNum)
        {
            if (lineNum < 0) throw new ArgumentNullException("lineNum");
            var b = new Bitmap(_width, _height);
            b.MakeTransparent();
            var g = Graphics.FromImage(b);
            g.Clear(Color.Transparent);
            g.PixelOffsetMode = PixelOffsetMode.HighQuality;
            g.SmoothingMode = SmoothingMode.HighQuality;
            for (var i = 0; i < lineNum; i++)
            {
                var p = new Pen(GetRandomDeepColor());
                var pt1 = new Point(_randomNumber.Next(1, (b.Width/5)*2), _randomNumber.Next(b.Height));
                var pt2 = new Point(_randomNumber.Next((b.Width/5)*3, b.Width), _randomNumber.Next(b.Height));
                g.DrawLine(p, pt1, pt2);
                p.Dispose();
            }

            return b;
        }

        #endregion

        #region 画随机噪点

        /// <summary>
        ///     画随机噪点
        /// </summary>
        /// <param name="pixNum">噪点的百分比</param>
        /// <returns></returns>
        public Bitmap DrawRandomPixel(Int32 pixNum)
        {
            var b = new Bitmap(_width, _height);
            b.MakeTransparent();
            var graph = Graphics.FromImage(b);
            graph.SmoothingMode = SmoothingMode.HighQuality;
            graph.InterpolationMode = InterpolationMode.HighQualityBilinear;

            //画噪点 
            for (var i = 0; i < (_height*_width)/pixNum; i++)
            {
                var x = _randomNumber.Next(b.Width);
                var y = _randomNumber.Next(b.Height);
                b.SetPixel(x, y, GetRandomDeepColor());
                //下移坐标重新画点
                if ((x + 1) < b.Width && (y + 1) < b.Height)
                {
                    //画图片的前景噪音点
                    graph.DrawRectangle(new Pen(Color.Silver), _randomNumber.Next(b.Width), _randomNumber.Next(b.Height),
                        1, 1);
                }
            }

            return b;
        }

        #endregion

        #region 画随机字符串中间连线

        /// <summary>
        ///     画随机字符串中间连线
        /// </summary>
        /// <returns></returns>
        private Bitmap DrawStringline()
        {
            var b = new Bitmap(_width, _height);
            b.MakeTransparent();
            var g = Graphics.FromImage(b);
            g.SmoothingMode = SmoothingMode.AntiAlias;

            var p = new Point[_length];
            for (var i = 0; i < _length; i++)
            {
                p[i] = _stringPoint[i];
            }
            g.DrawCurve(new Pen(GetRandomDeepColor(), 1), _stringPoint);

            return b;
        }

        #endregion

        #region 写入验证码的字符串

        /// <summary>
        ///     写入验证码的字符串
        /// </summary>
        private Bitmap DrawRandomString()
        {
            if (_fontMaxSize >= (_height/5)*4)
            {
                throw new ArgumentException("字体最大值参数FontMaxSize与验证码高度相近,这会导致描绘验证码字符串时出错,请重新设置参数！");
            }
            var b = new Bitmap(_width, _height);
            b.MakeTransparent();
            var g = Graphics.FromImage(b);

            g.Clear(Color.Transparent);
            g.PixelOffsetMode = PixelOffsetMode.Half;
            g.SmoothingMode = SmoothingMode.HighQuality;
            g.TextRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit;
            g.InterpolationMode = InterpolationMode.HighQualityBilinear;

            var chars = GetRandomString(_length).ToCharArray(); //拆散字符串成单字符数组
            _validationCode = new string(chars);

            //设置字体显示格式
            var format = new StringFormat(StringFormatFlags.NoClip)
            {
                Alignment = StringAlignment.Center,
                LineAlignment = StringAlignment.Center
            };
            var f = new FontFamily(GenericFontFamilies.Monospace);


            var charNum = chars.Length;

            var sPoint = new Point();
            for (var i = 0; i < _length; i++)
            {
                //定义字体
                var textFont = new Font(f, _randomNumber.Next(_fontMinSize, _fontMaxSize), FontStyle.Bold);
                //定义画刷,用于写字符串
                var textFontSize = Convert.ToInt32(textFont.Size);
                var point = new Point(_randomNumber.Next((_width/charNum)*i + 5, (_width/charNum)*(i + 1)),
                    _randomNumber.Next(_height/5 + textFontSize/2, _height - textFontSize/2));

                //如果当前字符X坐标小于字体的二分之一大小
                if (point.X < textFontSize/2)
                {
                    point.X = point.X + textFontSize/2;
                }
                //防止文字叠加
                if (i > 0 && (point.X - sPoint.X < (textFontSize/2 + textFontSize/2)))
                {
                    point.X = point.X + (textFontSize + 3);
                }
                //如果当前字符X坐标大于图片宽度,就减去字体的宽度
                if (point.X > (_width - textFontSize/2))
                {
                    point.X = _width - textFontSize/2;
                }

                sPoint = point;
                float angle = _randomNumber.Next(-_rotationAngle, _rotationAngle); //转动的度数
                g.TranslateTransform(point.X, point.Y); //移动光标到指定位置
                g.RotateTransform(angle);

                //设置渐变画刷  
                var retang = new Rectangle(0, 1, Convert.ToInt32(textFont.Size), Convert.ToInt32(textFont.Size));
                var c = GetRandomDeepColor();
                var brush2 = new LinearGradientBrush(retang, c, GetLightColor(c, 120), _randomNumber.Next(180));

                g.DrawString(chars[i].ToString(CultureInfo.InvariantCulture), textFont, brush2, 1, 1, format);

                g.RotateTransform(-angle); //转回去
                g.TranslateTransform(-point.X, -point.Y); //移动光标到指定位置,每个字符紧凑显示,避免被软件识别

                _stringPoint[i] = point;

                textFont.Dispose();
                brush2.Dispose();
            }
            return b;
        }

        #endregion

        #region 画干扰背景文字

        /// <summary>
        ///     画背景干扰文字
        /// </summary>
        /// <returns></returns>
        private Bitmap DrawRandBgString()
        {
            var b = new Bitmap(_width, _height);
            String[] randStr =
            {
                "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r",
                "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
                "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"
            };
            b.MakeTransparent();
            var g = Graphics.FromImage(b);

            g.Clear(Color.Transparent);
            g.PixelOffsetMode = PixelOffsetMode.HighQuality;
            g.SmoothingMode = SmoothingMode.HighQuality;
            g.TextRenderingHint = TextRenderingHint.AntiAlias;
            g.InterpolationMode = InterpolationMode.HighQualityBilinear;

            //设置字体显示格式
            var format = new StringFormat(StringFormatFlags.NoClip)
            {
                Alignment = StringAlignment.Center,
                LineAlignment = StringAlignment.Center
            };

            var f = new FontFamily(GenericFontFamilies.Serif);
            var textFont = new Font(f, _randomBackgroundStringFontSize, FontStyle.Underline);

            const int randAngle = 60; //随机转动角度

            for (var i = 0; i < RandomStringCount; i++)
            {
                Brush brush = new SolidBrush(GetRandomLightColor());
                var pot = new Point(_randomNumber.Next(5, _width - 5), _randomNumber.Next(5, _height - 5));
                //随机转动的度数
                float angle = _randomNumber.Next(-randAngle, randAngle);

                //转动画布
                g.RotateTransform(angle);
                g.DrawString(randStr[_randomNumber.Next(randStr.Length)], textFont, brush, pot, format);
                //转回去,为下一个字符做准备
                g.RotateTransform(-angle);
                //释放资源
                brush.Dispose();
            }
            textFont.Dispose();
            format.Dispose();
            f.Dispose();

            return b;
        }

        #endregion

        #region 生成随机字符串

        /// <summary>
        ///     生成随机字符串
        /// </summary>
        /// <returns></returns>
        private string GetRandomString(Int32 textLength)
        {
            var randomArray = _charCollection.Split(','); //将字符串生成数组     
            var arrayLength = randomArray.Length;
            var randomString = "";
            for (var i = 0; i < textLength; i++)
            {
                randomString += randomArray[_randomNumber.Next(0, arrayLength)];
            }
            return randomString; //长度是textLength +1
        }

        #endregion

        #region 内部方法:绘制验证码背景

        private void DrawBackground(HatchStyle hatchStyle)
        {
            //设置填充背景时用的笔刷
            var hBrush = new HatchBrush(hatchStyle, _backColor);

            //填充背景图片
            _image.FillRectangle(hBrush, 0, 0, _width, _height);
        }

        #endregion

        #region 根据指定长度,返回随机验证码

        /// <summary>
        ///     根据指定长度,返回随机验证码
        /// </summary>
        /// <param name="length">制定长度</param>
        /// <returns>随即验证码</returns>
        public string Next(int length)
        {
            _validationCode = GetRandomCode(length);
            return _validationCode;
        }

        #endregion

        #region 内部方法:返回指定长度的随机验证码字符串

        /// <summary>
        ///     根据指定大小返回随机验证码
        /// </summary>
        /// <param name="length">字符串长度</param>
        /// <returns>随机字符串</returns>
        private string GetRandomCode(int length)
        {
            var sb = new StringBuilder(6);

            for (var i = 0; i < length; i++)
            {
                sb.Append(Char.ConvertFromUtf32(RandomAZ09()));
            }

            return sb.ToString();
        }

        #endregion

        #region 合并图片

        /// <summary>
        ///     合并图片
        /// </summary>
        /// <param name="maps"></param>
        /// <returns></returns>
        private Bitmap MergerImg(params Bitmap[] maps)
        {
            var i = maps.Length;
            if (i == 0)
                throw new Exception("图片数不能够为0");
            //创建要显示的图片对象,根据参数的个数设置宽度            
            var backgroudImg = new Bitmap(i*12, 16);
            var g = Graphics.FromImage(backgroudImg);
            //清除画布,背景设置为白色            
            g.Clear(Color.White);
            for (var j = 0; j < i; j++)
            {
                g.DrawImageUnscaled(maps[j], 0, 0);
            }
            g.Dispose();
            return backgroudImg;
        }

        #endregion

        #region 生成不重复的随机数,该函数会消耗大量系统资源

        /// <summary>
        ///     生成不重复的随机数,该函数会消耗大量系统资源
        /// </summary>
        /// <returns></returns>
        private static int GetRandomSeed()
        {
            var bytes = new byte[4];
            var rng = new RNGCryptoServiceProvider();
            rng.GetBytes(bytes);
            return BitConverter.ToInt32(bytes, 0);
        }

        #endregion

        #region 缩放图片

        /// <summary>
        ///     缩放图片
        /// </summary>
        /// <param name="bmp">原始Bitmap</param>
        /// <param name="newW">新的宽度</param>
        /// <param name="newH">新的高度</param>
        /// <param name="mode">缩放质量</param>
        /// <returns>处理以后的图片</returns>
        public static Bitmap KiResizeImage(Bitmap bmp, int newW, int newH, InterpolationMode mode)
        {
            try
            {
                var b = new Bitmap(newW, newH);
                var g = Graphics.FromImage(b);
                // 插值算法的质量
                g.InterpolationMode = mode;
                g.DrawImage(bmp, new Rectangle(0, 0, newW, newH), new Rectangle(0, 0, bmp.Width, bmp.Height),
                    GraphicsUnit.Pixel);
                g.Dispose();
                return b;
            }
            catch
            {
                return null;
            }
        }

        #endregion

        #region 绘制圆角矩形

        /// <summary>
        ///     C# GDI+ 绘制圆角矩形
        /// </summary>
        /// <param name="g">Graphics 对象</param>
        /// <param name="rectangle">Rectangle 对象,圆角矩形区域</param>
        /// <param name="borderColor">边框颜色</param>
        /// <param name="borderWidth">边框宽度</param>
        /// <param name="r">圆角半径</param>
        private static void DrawRoundRectangle(Graphics g, Rectangle rectangle, Color borderColor, float borderWidth,
            int r)
        {
            // 如要使边缘平滑,请取消下行的注释
            g.SmoothingMode = SmoothingMode.HighQuality;

            // 由于边框也需要一定宽度,需要对矩形进行修正
            var p = new Pen(borderColor, borderWidth);
            // 调用 getRoundRectangle 得到圆角矩形的路径,然后再进行绘制
            g.DrawPath(p, GetRoundRectangle(rectangle, r));
        }

        #endregion

        #region 根据普通矩形得到圆角矩形的路径

        /// <summary>
        ///     根据普通矩形得到圆角矩形的路径
        /// </summary>
        /// <param name="rectangle">原始矩形</param>
        /// <param name="r">半径</param>
        /// <returns>图形路径</returns>
        private static GraphicsPath GetRoundRectangle(Rectangle rectangle, int r)
        {
            var l = 2*r;
            // 把圆角矩形分成八段直线、弧的组合,依次加到路径中
            var gp = new GraphicsPath();
            gp.AddLine(new Point(rectangle.X + r, rectangle.Y), new Point(rectangle.Right - r, rectangle.Y));
            gp.AddArc(new Rectangle(rectangle.Right - l, rectangle.Y, l, l), 270F, 90F);

            gp.AddLine(new Point(rectangle.Right, rectangle.Y + r), new Point(rectangle.Right, rectangle.Bottom - r));
            gp.AddArc(new Rectangle(rectangle.Right - l, rectangle.Bottom - l, l, l), 0F, 90F);

            gp.AddLine(new Point(rectangle.Right - r, rectangle.Bottom), new Point(rectangle.X + r, rectangle.Bottom));
            gp.AddArc(new Rectangle(rectangle.X, rectangle.Bottom - l, l, l), 90F, 90F);

            gp.AddLine(new Point(rectangle.X, rectangle.Bottom - r), new Point(rectangle.X, rectangle.Y + r));
            gp.AddArc(new Rectangle(rectangle.X, rectangle.Y, l, l), 180F, 90F);
            return gp;
        }

        #endregion

        #region 柔化

        /// <summary>
        ///     柔化
        /// </summary>
        /// <param name="b">原始图</param>
        /// <returns>输出图</returns>
        public static Bitmap KiBlur(Bitmap b)
        {
            if (b == null)
            {
                return null;
            }

            var w = b.Width;
            var h = b.Height;

            try
            {
                var bmpRtn = new Bitmap(w, h, PixelFormat.Format24bppRgb);

                var srcData = b.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadOnly,
                    PixelFormat.Format24bppRgb);
                var dstData = bmpRtn.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.WriteOnly,
                    PixelFormat.Format24bppRgb);

                unsafe
                {
                    var pIn = (byte*) srcData.Scan0.ToPointer();
                    var pOut = (byte*) dstData.Scan0.ToPointer();
                    var stride = srcData.Stride;

                    for (var y = 0; y < h; y++)
                    {
                        for (var x = 0; x < w; x++)
                        {
                            //取周围9点的值
                            if (x == 0 || x == w - 1 || y == 0 || y == h - 1)
                            {
                                //不做
                                pOut[0] = pIn[0];
                                pOut[1] = pIn[1];
                                pOut[2] = pIn[2];
                            }
                            else
                            {
                                int r2, r3, r4, r5, r6, r7, r8, r9;
                                int g1, g2, g3, g4, g5, g6, g7, g8, g9;
                                int b1, b2, b3, b4, b5, b6, b7, b8, b9;

                                float vR, vG, vB;

                                //左上
                                var p = pIn - stride - 3;
                                int r1 = p[2];
                                g1 = p[1];
                                b1 = p[0];

                                //正上
                                p = pIn - stride;
                                r2 = p[2];
                                g2 = p[1];
                                b2 = p[0];

                                //右上
                                p = pIn - stride + 3;
                                r3 = p[2];
                                g3 = p[1];
                                b3 = p[0];

                                //左侧
                                p = pIn - 3;
                                r4 = p[2];
                                g4 = p[1];
                                b4 = p[0];

                                //右侧
                                p = pIn + 3;
                                r5 = p[2];
                                g5 = p[1];
                                b5 = p[0];

                                //右下
                                p = pIn + stride - 3;
                                r6 = p[2];
                                g6 = p[1];
                                b6 = p[0];

                                //正下
                                p = pIn + stride;
                                r7 = p[2];
                                g7 = p[1];
                                b7 = p[0];

                                //右下
                                p = pIn + stride + 3;
                                r8 = p[2];
                                g8 = p[1];
                                b8 = p[0];

                                //自己
                                p = pIn;
                                r9 = p[2];
                                g9 = p[1];
                                b9 = p[0];

                                vR = r1 + r2 + r3 + r4 + r5 + r6 + r7 + r8 + r9;
                                vG = g1 + g2 + g3 + g4 + g5 + g6 + g7 + g8 + g9;
                                vB = b1 + b2 + b3 + b4 + b5 + b6 + b7 + b8 + b9;

                                vR /= 9;
                                vG /= 9;
                                vB /= 9;

                                pOut[0] = (byte) vB;
                                pOut[1] = (byte) vG;
                                pOut[2] = (byte) vR;
                            }

                            pIn += 3;
                            pOut += 3;
                        } // end of x

                        pIn += srcData.Stride - w*3;
                        pOut += srcData.Stride - w*3;
                    } // end of y
                }

                b.UnlockBits(srcData);
                bmpRtn.UnlockBits(dstData);

                return bmpRtn;
            }
            catch
            {
                return null;
            }
        } // end of KiBlur

        #endregion

        #region 图片去色（图片黑白化）

        /// <summary>
        ///     图片去色（图片黑白化）
        /// </summary>
        /// <param name="original">一个需要处理的图片</param>
        /// <returns></returns>
        public static Bitmap MakeGrayscale(Bitmap original)
        {
            //create a blank bitmap the same size as original
            var newBitmap = new Bitmap(original.Width, original.Height);

            //get a graphics object from the new image
            var g = Graphics.FromImage(newBitmap);
            g.SmoothingMode = SmoothingMode.HighQuality;
            //create the grayscale ColorMatrix
            var colorMatrix = new ColorMatrix(new[]
            {
                new[] {.3f, .3f, .3f, 0, 0},
                new[] {.59f, .59f, .59f, 0, 0},
                new[] {.11f, .11f, .11f, 0, 0},
                new float[] {0, 0, 0, 1, 0},
                new float[] {0, 0, 0, 0, 1}
            });

            //create some image attributes
            var attributes = new ImageAttributes();

            //set the color matrix attribute
            attributes.SetColorMatrix(colorMatrix);

            //draw the original image on the new image
            //using the grayscale color matrix
            g.DrawImage(original, new Rectangle(0, 0, original.Width, original.Height),
                0, 0, original.Width, original.Height, GraphicsUnit.Pixel, attributes);

            //dispose the Graphics object
            g.Dispose();
            return newBitmap;
        }

        #endregion

        #region 增加或减少亮度

        /// <summary>
        ///     增加或减少亮度
        /// </summary>
        /// <param name="img">System.Drawing.Image Source </param>
        /// <param name="valBrightness">0~255</param>
        /// <returns></returns>
        public Bitmap AdjustBrightness(Image img, int valBrightness)
        {
            // 读入欲转换的图片并转成为 Bitmap
            var bitmap = new Bitmap(img);

            for (var y = 0; y < bitmap.Height; y++)
            {
                for (var x = 0; x < bitmap.Width; x++)
                {
                    // 取得每一个 pixel
                    var pixel = bitmap.GetPixel(x, y);

                    // 判断 如果处理过后 255 就设定为 255 如果小于则设定为 0
                    var pR = ((pixel.R + valBrightness > 255) ? 255 : pixel.R + valBrightness) < 0
                        ? 0
                        : ((pixel.R + valBrightness > 255) ? 255 : pixel.R + valBrightness);
                    var pG = ((pixel.G + valBrightness > 255) ? 255 : pixel.G + valBrightness) < 0
                        ? 0
                        : ((pixel.G + valBrightness > 255) ? 255 : pixel.G + valBrightness);
                    var pB = ((pixel.B + valBrightness > 255) ? 255 : pixel.B + valBrightness) < 0
                        ? 0
                        : ((pixel.B + valBrightness > 255) ? 255 : pixel.B + valBrightness);

                    // 将改过的 RGB 写回
                    var newColor = Color.FromArgb(pixel.A, pR, pG, pB);

                    bitmap.SetPixel(x, y, newColor);
                }
            }
            // 回传结果
            return bitmap;
        }

        #endregion

        #region 浮雕效果

        /// <summary>
        ///     浮雕效果
        /// </summary>
        /// <param name="src">一个图片实例</param>
        /// <returns></returns>
        public Bitmap AdjustToStone(Bitmap src)
        {
            // 依照 Format24bppRgb 每三个表示一 Pixel 0: 蓝 1: 绿 2: 红
            var bitmapData = src.LockBits(new Rectangle(0, 0, src.Width, src.Height), ImageLockMode.ReadWrite,
                PixelFormat.Format24bppRgb);

            unsafe
            {
                // 抓住第一个 Pixel 第一个数值
                var p = (byte*) (void*) bitmapData.Scan0;

                // 跨步值 - 宽度 *3 可以算出畸零地 之后跳到下一行
                var nOffset = bitmapData.Stride - src.Width*3;

                for (var y = 0; y < src.Height; ++y)
                {
                    for (var x = 0; x < src.Width; ++x)
                    {
                        // 为了理解方便 所以特地在命名
                        int g, b;
                        // 先取得下一个 Pixel
                        var q = p + 3;
                        var r = Math.Abs(p[2] - q[2] + 128);
                        r = r < 0 ? 0 : r;
                        r = r > 255 ? 255 : r;
                        p[2] = (byte) r;

                        g = Math.Abs(p[1] - q[1] + 128);
                        g = g < 0 ? 0 : g;
                        g = g > 255 ? 255 : g;
                        p[1] = (byte) g;

                        b = Math.Abs(p[0] - q[0] + 128);
                        b = b < 0 ? 0 : b;
                        b = b > 255 ? 255 : b;
                        p[0] = (byte) b;

                        // 跳去下一个 Pixel
                        p += 3;
                    }
                    // 跨越畸零地
                    p += nOffset;
                }
            }
            src.UnlockBits(bitmapData);
            return src;
        }

        #endregion

        #region 水波纹效果

        /// <summary>
        ///     水波纹效果
        /// </summary>
        /// <param name="src"></param>
        /// <param name="nWave">坡度</param>
        /// <returns></returns>
        public Bitmap AdjustRippleEffect(Bitmap src, short nWave)
        {
            var nWidth = src.Width;
            var nHeight = src.Height;

            // 透过公式进行水波纹的采样

            var fp = new PointF[nWidth, nHeight];

            var pt = new Point[nWidth, nHeight];

            new Point {X = nWidth/2, Y = nHeight/2};

            //先取样将水波纹座标跟RGB取出
            for (var x = 0; x < nWidth; ++x)
                for (var y = 0; y < nHeight; ++y)
                {
                    var xo = (nWave*Math.Sin(2.0*3.1415*y/128.0));
                    var yo = (nWave*Math.Cos(2.0*3.1415*x/128.0));

                    var newX = (x + xo);
                    var newY = (y + yo);

                    if (newX > 0 && newX < nWidth)
                    {
                        fp[x, y].X = (float) newX;
                        pt[x, y].X = (int) newX;
                    }
                    else
                    {
                        fp[x, y].X = (float) 0.0;
                        pt[x, y].X = 0;
                    }


                    if (newY > 0 && newY < nHeight)
                    {
                        fp[x, y].Y = (float) newY;
                        pt[x, y].Y = (int) newY;
                    }
                    else
                    {
                        fp[x, y].Y = (float) 0.0;
                        pt[x, y].Y = 0;
                    }
                }


            //进行合成
            var bSrc = (Bitmap) src.Clone();

            // 依照 Format24bppRgb 每三个表示一 Pixel 0: 蓝 1: 绿 2: 红
            var bitmapData = src.LockBits(new Rectangle(0, 0, src.Width, src.Height), ImageLockMode.ReadWrite,
                PixelFormat.Format24bppRgb);
            var bmSrc = bSrc.LockBits(new Rectangle(0, 0, bSrc.Width, bSrc.Height), ImageLockMode.ReadWrite,
                PixelFormat.Format24bppRgb);

            var scanline = bitmapData.Stride;

            var scan0 = bitmapData.Scan0;
            var srcScan0 = bmSrc.Scan0;

            unsafe
            {
                var p = (byte*) (void*) scan0;
                var pSrc = (byte*) (void*) srcScan0;

                var nOffset = bitmapData.Stride - src.Width*3;

                for (var y = 0; y < nHeight; ++y)
                {
                    for (var x = 0; x < nWidth; ++x)
                    {
                        var xOffset = pt[x, y].X;
                        var yOffset = pt[x, y].Y;

                        if (yOffset >= 0 && yOffset < nHeight && xOffset >= 0 && xOffset < nWidth)
                        {
                            p[0] = pSrc[(yOffset*scanline) + (xOffset*3)];
                            p[1] = pSrc[(yOffset*scanline) + (xOffset*3) + 1];
                            p[2] = pSrc[(yOffset*scanline) + (xOffset*3) + 2];
                        }

                        p += 3;
                    }
                    p += nOffset;
                }
            }

            src.UnlockBits(bitmapData);
            bSrc.UnlockBits(bmSrc);

            return src;
        }

        #endregion

        #region 调整曝光度值

        /// <summary>
        ///     调整曝光度值
        /// </summary>
        /// <param name="src">原图</param>
        /// <param name="r"></param>
        /// <param name="g"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public Bitmap AdjustGamma(Bitmap src, double r, double g, double b)
        {
            // 判断是不是在0.2~5 之间
            r = Math.Min(Math.Max(0.2, r), 5);
            g = Math.Min(Math.Max(0.2, g), 5);
            b = Math.Min(Math.Max(0.2, b), 5);

            // 依照 Format24bppRgb 每三个表示一 Pixel 0: 蓝 1: 绿 2: 红
            var bitmapData = src.LockBits(new Rectangle(0, 0, src.Width, src.Height), ImageLockMode.ReadWrite,
                PixelFormat.Format24bppRgb);

            unsafe
            {
                // 抓住第一个 Pixel 第一个数值
                var p = (byte*) (void*) bitmapData.Scan0;

                // 跨步值 - 宽度 *3 可以算出畸零地 之后跳到下一行
                var nOffset = bitmapData.Stride - src.Width*3;

                for (var y = 0; y < src.Height; y++)
                {
                    for (var x = 0; x < src.Width; x++)
                    {
                        p[2] = (byte) Math.Min(255, (int) ((255.0*Math.Pow(p[2]/255.0, 1.0/r)) + 0.5));
                        p[1] = (byte) Math.Min(255, (int) ((255.0*Math.Pow(p[1]/255.0, 1.0/g)) + 0.5));
                        p[0] = (byte) Math.Min(255, (int) ((255.0*Math.Pow(p[0]/255.0, 1.0/b)) + 0.5));


                        // 跳去下一个 Pixel
                        p += 3;
                    }
                    // 跨越畸零地
                    p += nOffset;
                }
            }
            src.UnlockBits(bitmapData);
            return src;
        }

        #endregion

        #region 高对比,对过深的颜色调浅,过浅的颜色调深

        /// <summary>
        ///     高对比,对过深的颜色调浅,过浅的颜色调深
        /// </summary>
        /// <param name="src"></param>
        /// <param name="effectThreshold"> 高对比程度 -100~100</param>
        /// <returns></returns>
        public Bitmap Contrast(Bitmap src, float effectThreshold)
        {
            // 依照 Format24bppRgb 每三个表示一 Pixel 0: 蓝 1: 绿 2: 红
            var bitmapData = src.LockBits(new Rectangle(0, 0, src.Width, src.Height), ImageLockMode.ReadWrite,
                PixelFormat.Format24bppRgb);

            // 判断是否在 -100~100
            effectThreshold = effectThreshold < -100 ? -100 : effectThreshold;
            effectThreshold = effectThreshold > 100 ? 100 : effectThreshold;

            effectThreshold = (float) ((100.0 + effectThreshold)/100.0);
            effectThreshold *= effectThreshold;

            unsafe
            {
                // 抓住第一个 Pixel 第一个数值 www.it165.net
                var p = (byte*) (void*) bitmapData.Scan0;

                // 跨步值 - 宽度 *3 可以算出畸零地 之后跳到下一行
                var nOffset = bitmapData.Stride - src.Width*3;

                for (var y = 0; y < src.Height; y++)
                {
                    for (var x = 0; x < src.Width; x++)
                    {
                        // 公式  (Red/255)-0.5= 偏离中间值程度
                        // ((偏离中间值程度 * 影响范围)+0.4 ) * 255
                        var buffer = ((((p[2]/255.0) - 0.5)*effectThreshold) + 0.5)*255.0;
                        buffer = buffer > 255 ? 255 : buffer;
                        buffer = buffer < 0 ? 0 : buffer;
                        p[2] = (byte) buffer;

                        buffer = ((((p[1]/255.0) - 0.5)*effectThreshold) + 0.5)*255.0;
                        buffer = buffer > 255 ? 255 : buffer;
                        buffer = buffer < 0 ? 0 : buffer;
                        p[1] = (byte) buffer;


                        buffer = ((((p[0]/255.0) - 0.5)*effectThreshold) + 0.5)*255.0;
                        buffer = buffer > 255 ? 255 : buffer;
                        buffer = buffer < 0 ? 0 : buffer;
                        p[0] = (byte) buffer;

                        // 跳去下一个 Pixel
                        p += 3;
                    }
                    // 跨越畸零地
                    p += nOffset;
                }
            }
            src.UnlockBits(bitmapData);
            return src;
        }

        #endregion

        #region 对图片进行雾化效果

        /// <summary>
        ///     对图片进行雾化效果
        /// </summary>
        /// <param name="bmp"></param>
        /// <returns></returns>
        public Bitmap Atomization(Bitmap bmp)
        {
            var height = bmp.Height;
            var width = bmp.Width;
            var newBitmap = new Bitmap(width, height);
            var oldBitmap = bmp;
            for (var x = 1; x < width - 1; x++)
            {
                for (var y = 1; y < height - 1; y++)
                {
                    var random = new Random(Guid.NewGuid().GetHashCode());
                    var k = random.Next(123456);
                    //像素块大小
                    var dx = x + k%19;
                    var dy = y + k%19;
                    if (dx >= width)
                        dx = width - 1;
                    if (dy >= height)
                        dy = height - 1;
                    var pixel = oldBitmap.GetPixel(dx, dy);
                    newBitmap.SetPixel(x, y, pixel);
                }
            }
            return newBitmap;
        }

        #endregion

        #region 定义和初始化配置字段

        //用户存取验证码字符串
        /// <summary>
        ///     边框样式
        /// </summary>
        public enum BorderStyle
        {
            /// <summary>
            ///     无边框
            /// </summary>
            None,

            /// <summary>
            ///     矩形边框
            /// </summary>
            Rectangle,

            /// <summary>
            ///     圆角边框
            /// </summary>
            RoundRectangle
        }

        private readonly Random _randomNumber;
        private readonly Point[] _stringPoint;
        private Color _backColor = Color.FromArgb(243, 255, 255);
        private Int32 _bezierCount = 5;

        private String _charCollection =
            "2,3,4,5,6,7,8,9,a,s,d,f,g,h,z,c,v,b,n,m,k,q,w,e,r,t,y,u,p,A,S,D,F,G,H,Z,C,V,B,N,M,K,Q,W,E,R,T,Y,U,P";

        private Color[] _fontColor = {};

        private String[] _fontFamily =
        {
            "Times New Roman", "MS Mincho", "Book Antiqua", "Gungsuh", "PMingLiU", "Impact",
            "Verdana", "Microsoft Sans Serif", "Comic Sans MS", "Arial", "宋体"
        };

        private Int32 _fontMaxSize = 45;
        private Int32 _fontMinSize = 35;
        private Int32 _height = 60;
        private Graphics _image;
        private Boolean _isPixel = true;
        private Boolean _isRandString = true;
        private Int32 _length = 5;
        private Int32 _lineCount = 5;
        private Int32 _randomBackgroundStringFontSize = 15;
        private Int32 _rotationAngle = 45;

        private String _validationCode = String.Empty;
        private Int32 _width = 280;

        /// <summary>
        ///     获取系统生成的随机验证码
        /// </summary>
        public String ValidationCode
        {
            get { return _validationCode; }
        }

        /// <summary>
        ///     获取和设置验证码字符串的长度
        /// </summary>
        public Int32 Length
        {
            get { return _length; }
            set { _length = value; }
        }

        /// <summary>
        ///     验证码的宽度
        /// </summary>
        public Int32 Width
        {
            get { return _width; }
            set { _width = value; }
        }

        /// <summary>
        ///     验证码的高度
        /// </summary>
        public Int32 Height
        {
            get { return _height; }
            set { _height = value; }
        }

        /// <summary>
        ///     验证码字体列表
        /// </summary>
        public String[] Fonts
        {
            get { return _fontFamily; }
            set { _fontFamily = value; }
        }

        /// <summary>
        ///     验证码字体的最小值
        /// </summary>
        public Int32 FontMinSize
        {
            get { return _fontMinSize; }
            set { _fontMinSize = value; }
        }

        /// <summary>
        ///     验证码字体的最大值
        /// </summary>
        public Int32 FontMaxSize
        {
            get { return _fontMaxSize; }
            set { _fontMaxSize = value; }
        }

        /// <summary>
        ///     验证码字体的颜色
        /// </summary>
        public Color[] FontColor
        {
            get { return _fontColor; }
            set { _fontColor = value; }
        }

        /// <summary>
        ///     验证码的背景色
        /// </summary>
        public Color BackgroundColor
        {
            get { return _backColor; }
            set { _backColor = value; }
        }

        /// <summary>
        ///     贝塞尔曲线的条数
        /// </summary>
        public Int32 BezierCount
        {
            get { return _bezierCount; }
            set { _bezierCount = value; }
        }

        /// <summary>
        ///     直线条数
        /// </summary>
        public Int32 LineCount
        {
            get { return _lineCount; }
            set { _lineCount = value; }
        }

        /// <summary>
        ///     随机字符串行表
        /// </summary>
        public String CharCollection
        {
            get { return _charCollection; }
            set { _charCollection = value; }
        }

        /// <summary>
        ///     是否添加噪点
        /// </summary>
        public Boolean IsPixel
        {
            get { return _isPixel; }
            set { _isPixel = value; }
        }

        /// <summary>
        ///     是否添加随机噪点字符串
        /// </summary>
        public Boolean IsRandString
        {
            get { return _isRandString; }
            set { _isRandString = value; }
        }

        /// <summary>
        ///     随机背景字符串的个数
        /// </summary>
        public Int32 RandomStringCount { get; set; }

        /// <summary>
        ///     随机背景字符串的大小
        /// </summary>
        public Int32 RandomBackgroundStringFontSize
        {
            get { return _randomBackgroundStringFontSize; }
            set { _randomBackgroundStringFontSize = value; }
        }

        /// <summary>
        ///     是否对图片进行扭曲
        /// </summary>
        public Boolean IsTwist { get; set; }

        /// <summary>
        ///     验证码字符串随机转动的角度的最大值
        /// </summary>
        public Int32 RotationAngle
        {
            get { return _rotationAngle; }
            set { _rotationAngle = value; }
        }

        /// <summary>
        ///     设置或获取边框样式
        /// </summary>
        public BorderStyle Border { get; set; }

        /// <summary>
        ///     对验证码图片进行高斯模糊的阀值
        /// </summary>
        public Double GaussianDeviation { get; set; }

        /// <summary>
        ///     对图片进行暗度和亮度的调整,如果该值为0
        /// </summary>
        public Int32 IsChangeBrightness { get; set; }

        #endregion

        #region 内部方法:产生随机数和随机点

        /// <summary>
        ///     产生0-9 A-Z的随机字符代码
        /// </summary>
        /// <returns>字符代码</returns>
        private int RandomAZ09()
        {
            var result = 48;
            var ram = new Random();
            var i = ram.Next(2);

            switch (i)
            {
                case 0:
                    result = ram.Next(48, 58);
                    break;
                case 1:
                    result = ram.Next(65, 91);
                    break;
            }

            return result;
        }

        /// <summary>
        ///     返回一个随机点,该随机点范围在验证码背景大小范围内
        /// </summary>
        /// <returns>Point对象</returns>
        private Point RandomPoint()
        {
            var ram = new Random();
            var point = new Point(ram.Next(_width), ram.Next(_height));
            return point;
        }

        #endregion

        #region 随机生成颜色值

        /// <summary>
        ///     生成随机深颜色
        /// </summary>
        /// <returns></returns>
        public Color GetRandomDeepColor()
        {
            const int redLow = 160;
            const int greenLow = 100;
            const int blueLow = 160;
            var nRed = _randomNumber.Next(redLow);
            var nGreen = _randomNumber.Next(greenLow);
            var nBlue = _randomNumber.Next(blueLow);
            var color = Color.FromArgb(nRed, nGreen, nBlue);
            return color;
        }

        /// <summary>
        ///     生成随机浅颜色
        /// </summary>
        /// <returns>randomColor</returns>
        public Color GetRandomLightColor()
        {
            const int low = 180; //色彩的下限
            const int high = 255; //色彩的上限      
            var nRed = _randomNumber.Next(high)%(high - low) + low;
            var nGreen = _randomNumber.Next(high)%(high - low) + low;
            var nBlue = _randomNumber.Next(high)%(high - low) + low;
            var color = Color.FromArgb(nRed, nGreen, nBlue);
            return color;
        }

        /// <summary>
        ///     生成随机颜色值
        /// </summary>
        /// <returns></returns>
        public Color GetRandomColor()
        {
            const int low = 10; //色彩的下限
            const int high = 255; //色彩的上限    
            var nRed = _randomNumber.Next(high)%(high - low) + low;
            var nGreen = _randomNumber.Next(high)%(high - low) + low;
            var nBlue = _randomNumber.Next(high)%(high - low) + low;
            var color = Color.FromArgb(nRed, nGreen, nBlue);
            return color;
        }

        /// <summary>
        ///     获取与当前颜色值相加后的颜色
        /// </summary>
        /// <param name="c"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public Color GetLightColor(Color c, Int32 value)
        {
            int nRed = c.R, nGreen = c.G, nBlue = c.B; //越大颜色越浅
            if (nRed + value < 255 && nRed + value > 0)
            {
                nRed = c.R + 40;
            }
            if (nGreen + value < 255 && nGreen + value > 0)
            {
                nGreen = c.G + 40;
            }
            if (nBlue + value < 255 && nBlue + value > 0)
            {
                nBlue = c.B + 40;
            }
            var color = Color.FromArgb(nRed, nGreen, nBlue);
            return color;
        }

        #endregion

        #region 滤镜

        /// <summary>
        ///     红色滤镜
        /// </summary>
        /// <param name="bitmap">Bitmap</param>
        /// <param name="threshold">阀值 -255~255</param>
        /// <returns></returns>
        public Bitmap AdjustToRed(Bitmap bitmap, int threshold)
        {
            for (var y = 0; y < bitmap.Height; y++)
            {
                for (var x = 0; x < bitmap.Width; x++)
                {
                    // 取得每一个 pixel
                    var pixel = bitmap.GetPixel(x, y);
                    var pR = pixel.R + threshold;
                    pR = Math.Max(pR, 0);
                    pR = Math.Min(255, pR);
                    // 将改过的 RGB 写回
                    // 只写入红色的值 , G B 都放零
                    var newColor = Color.FromArgb(pixel.A, pR, 0, 0);
                    bitmap.SetPixel(x, y, newColor);
                }
            }
            // 回传结果
            return bitmap;
        }

        /// <summary>
        ///     绿色滤镜
        /// </summary>
        /// <param name="bitmap">一个图片实例</param>
        /// <param name="threshold">阀值 -255~+255</param>
        /// <returns></returns>
        public Bitmap AdjustToGreen(Bitmap bitmap, int threshold)
        {
            for (var y = 0; y < bitmap.Height; y++)
            {
                for (var x = 0; x < bitmap.Width; x++)
                {
                    // 取得每一个 pixel
                    var pixel = bitmap.GetPixel(x, y);
                    //判断是否超过255 如果超过就是255 
                    var pG = pixel.G + threshold;
                    //如果小于0就为0
                    if (pG > 255) pG = 255;
                    if (pG < 0) pG = 0;
                    // 将改过的 RGB 写回
                    // 只写入绿色的值 , R B 都放零
                    var newColor = Color.FromArgb(pixel.A, 0, pG, 0);
                    bitmap.SetPixel(x, y, newColor);
                }
            }
            // 回传结果
            return bitmap;
        }

        /// <summary>
        ///     蓝色滤镜
        /// </summary>
        /// <param name="bitmap">一个图片实例</param>
        /// <param name="threshold">阀值 -255~255</param>
        /// <returns></returns>
        public Bitmap AdjustToBlue(Bitmap bitmap, int threshold)
        {
            for (var y = 0; y < bitmap.Height; y++)
            {
                for (var x = 0; x < bitmap.Width; x++)
                {
                    // 取得每一个 pixel
                    var pixel = bitmap.GetPixel(x, y);
                    //判断是否超过255 如果超过就是255 
                    var pB = pixel.B + threshold;
                    //如果小于0就为0
                    if (pB > 255) pB = 255;
                    if (pB < 0) pB = 0;
                    // 将改过的 RGB 写回
                    // 只写入蓝色的值 , R G 都放零
                    var newColor = Color.FromArgb(pixel.A, 0, 0, pB);
                    bitmap.SetPixel(x, y, newColor);
                }
            }
            // 回传结果
            return bitmap;
        }

        /// <summary>
        ///     调整 RGB 色调
        /// </summary>
        /// <param name="bitmap"></param>
        /// <param name="thresholdRed">红色阀值</param>
        /// <param name="thresholdBlue">蓝色阀值</param>
        /// <param name="thresholdGreen">绿色阀值</param>
        /// <returns></returns>
        public Bitmap AdjustToCustomColor(Bitmap bitmap, int thresholdRed, int thresholdGreen, int thresholdBlue)
        {
            for (var y = 0; y < bitmap.Height; y++)
            {
                for (var x = 0; x < bitmap.Width; x++)
                {
                    // 取得每一个 pixel
                    var pixel = bitmap.GetPixel(x, y);
                    //判断是否超过255 如果超过就是255 
                    var pG = pixel.G + thresholdGreen;
                    //如果小于0就为0
                    if (pG > 255) pG = 255;
                    if (pG < 0) pG = 0;
                    //判断是否超过255 如果超过就是255 
                    var pR = pixel.R + thresholdRed;
                    //如果小于0就为0
                    if (pR > 255) pR = 255;
                    if (pR < 0) pR = 0;
                    //判断是否超过255 如果超过就是255 
                    var pB = pixel.B + thresholdBlue;
                    //如果小于0就为0
                    if (pB > 255) pB = 255;
                    if (pB < 0) pB = 0;
                    // 将改过的 RGB 写回
                    // 只写入绿色的值 , R B 都放零
                    var newColor = Color.FromArgb(pixel.A, pR, pG, pB);
                    bitmap.SetPixel(x, y, newColor);
                }
            }
            return bitmap;
        }

        #endregion
    }

    #endregion

    #region 高斯模糊算法

    /// <summary>
    ///     高斯模糊算法
    /// </summary>
    public class Gaussian
    {
        public static double[,] Calculate1DSampleKernel(double deviation, int size)
        {
            var ret = new double[size, 1];
            var half = size/2;
            for (var i = 0; i < size; i++)
            {
                ret[i, 0] = 1/(Math.Sqrt(2*Math.PI)*deviation)*Math.Exp(-(i - half)*(i - half)/(2*deviation*deviation));
            }
            return ret;
        }

        public static double[,] Calculate1DSampleKernel(double deviation)
        {
            var size = (int) Math.Ceiling(deviation*3)*2 + 1;
            return Calculate1DSampleKernel(deviation, size);
        }

        public static double[,] CalculateNormalized1DSampleKernel(double deviation)
        {
            return NormalizeMatrix(Calculate1DSampleKernel(deviation));
        }

        public static double[,] NormalizeMatrix(double[,] matrix)
        {
            var ret = new double[matrix.GetLength(0), matrix.GetLength(1)];
            double sum = 0;
            for (var i = 0; i < ret.GetLength(0); i++)
            {
                for (var j = 0; j < ret.GetLength(1); j++)
                    sum += matrix[i, j];
            }
            if (Math.Abs(sum) > 0)
            {
                for (var i = 0; i < ret.GetLength(0); i++)
                {
                    for (var j = 0; j < ret.GetLength(1); j++)
                        ret[i, j] = matrix[i, j]/sum;
                }
            }
            return ret;
        }

        public static double[,] GaussianConvolution(double[,] matrix, double deviation)
        {
            var kernel = CalculateNormalized1DSampleKernel(deviation);
            var res1 = new double[matrix.GetLength(0), matrix.GetLength(1)];
            var res2 = new double[matrix.GetLength(0), matrix.GetLength(1)];
            //x-direction
            for (var i = 0; i < matrix.GetLength(0); i++)
            {
                for (var j = 0; j < matrix.GetLength(1); j++)
                    res1[i, j] = ProcessPoint(matrix, i, j, kernel, 0);
            }
            //y-direction
            for (var i = 0; i < matrix.GetLength(0); i++)
            {
                for (var j = 0; j < matrix.GetLength(1); j++)
                    res2[i, j] = ProcessPoint(res1, i, j, kernel, 1);
            }
            return res2;
        }

        private static double ProcessPoint(double[,] matrix, int x, int y, double[,] kernel, int direction)
        {
            double res = 0;
            var half = kernel.GetLength(0)/2;
            for (var i = 0; i < kernel.GetLength(0); i++)
            {
                var cox = direction == 0 ? x + i - half : x;
                var coy = direction == 1 ? y + i - half : y;
                if (cox >= 0 && cox < matrix.GetLength(0) && coy >= 0 && coy < matrix.GetLength(1))
                {
                    res += matrix[cox, coy]*kernel[i, 0];
                }
            }
            return res;
        }

        /// <summary>
        ///     对颜色值进行灰色处理
        /// </summary>
        /// <param name="cr"></param>
        /// <returns></returns>
        private Color GrayScale(Color cr)
        {
            return Color.FromArgb(cr.A, (int) (cr.R*.3 + cr.G*.59 + cr.B*0.11),
                (int) (cr.R*.3 + cr.G*.59 + cr.B*0.11),
                (int) (cr.R*.3 + cr.G*.59 + cr.B*0.11));
        }

        /// <summary>
        ///     对图片进行高斯模糊
        /// </summary>
        /// <param name="d">模糊数值,数值越大模糊越很</param>
        /// <param name="image">一个需要处理的图片</param>
        /// <returns></returns>
        public Bitmap FilterProcessImage(double d, Bitmap image)
        {
            var ret = new Bitmap(image.Width, image.Height);
            var matrixR = new Double[image.Width, image.Height];
            var matrixG = new Double[image.Width, image.Height];
            var matrixB = new Double[image.Width, image.Height];
            for (var i = 0; i < image.Width; i++)
            {
                for (var j = 0; j < image.Height; j++)
                {
                    matrixR[i, j] = image.GetPixel(i, j).R;
                    matrixG[i, j] = image.GetPixel(i, j).G;
                    matrixB[i, j] = image.GetPixel(i, j).B;
                }
            }
            matrixR = GaussianConvolution(matrixR, d);
            matrixG = GaussianConvolution(matrixG, d);
            matrixB = GaussianConvolution(matrixB, d);
            for (var i = 0; i < image.Width; i++)
            {
                for (var j = 0; j < image.Height; j++)
                {
                    var r = (int) Math.Min(255, matrixR[i, j]);
                    var g = (int) Math.Min(255, matrixG[i, j]);
                    var b = (int) Math.Min(255, matrixB[i, j]);
                    ret.SetPixel(i, j, Color.FromArgb(r, g, b));
                }
            }
            return ret;
        }
    }

    #endregion
}